﻿#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//VS实用的调试技巧
//什么是bug：bug本意是“昆⾍”或“⾍⼦”，现在⼀般是指在电脑系统或程序中，隐藏着的⼀些未被发现的缺陷或问题，简称程序漏洞
//什么是调试(debug)：当我们发现程序中存在的问题的时候，那下⼀步就是找到问题，并修复问题。这个找问题的过程叫称为调试，英⽂叫debug（消灭bug）的意思。
//调试其实就是当程序已经存在问题的时候，去找问题的过程，调试是一个动作


//Debug：通常称为调试版本，它包含调试信息，并且不作任何优化，便于程序员调试程序；
//程序员在写代码的时候，需要经常性的调试代码，就将这⾥设置为 debug ，
// 这样编译产生的是debug 版本的可执行程序，其中包含调试信息，是可以直接调试的。

//Release：称为发布版本，它往往是进⾏了各种优化，使得程序在代码大⼩和运行速度上都是最优的，
//以便用户很好地使⽤。当程序员写完代码，测试再对程序进行测试，直到程序的质量符合交付给用户使⽤的标准，这个时候就会设置为 release ，
//编译产⽣的就是 release 版本的可执⾏程序，这个版本是用户使⽤的，⽆需包含调试信息等


//int main()
//{
//	int arr[10] = { 0 };
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//
//	return 0;
//}



//调试最常使⽤的⼏个快捷键：
//
//F9：创建断点和取消断点
//断点的作⽤是可以在程序的任意位置设置断点，打上断点就可以使得程序执⾏到想要的位置暂停执
//⾏，接下来我们就可以使⽤F10，F11这些快捷键，观察代码的执⾏细节。
//条件断点：满⾜这个条件，才触发断点

//F5：是让程序执行到（运行逻辑上的）下一个断点处
//F5：启动调试，经常用来直接跳到下⼀个断点处，⼀般是和F9配合使⽤。

//F10：逐过程，通常⽤来处理⼀个过程，⼀个过程可以是⼀次函数调⽤，或者是⼀条语句。

//F11：逐语句，就是每次都执⾏⼀条语句，但是这个快捷键可以使我们的执⾏逻辑进⼊函数内部。
//     在函数调⽤的地⽅，想进⼊函数观察细节，必须使⽤F11，如果使⽤F10，直接完成函数调⽤。

//CTRL + F5：开始执⾏不调试，如果你想让程序直接运⾏起来⽽不调试就可以直接使⽤。


//int main()
//{
//	int arr[10] = { 0 };
//	int i = 0;
//
//	//给数组元素赋值
//	for (i = 0; i < 10; i++)
//	{
//		arr[i] = i + 1;
//		//scanf("%d", &arr[i]);
//	}
//
//	//打印数组的内容
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//
//	return 0;
//}


//F10 F11
//void test()
//{
//	printf("hehe\n");
//	int n = 4 + 5;
//	printf("%n", n);
//}
//int main()
//{
//	int a = 10;
//	int b = 20;
//	int c = a + b;
//	test();
//	printf("hehe\n");
//
//	return 0;
//}



//int main()
//{
//	int arr[10] = { 0 };
//	int num = 100;
//	char c = 'w';
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		arr[i] = i;
//	}
//	return 0;
//}



//求 1!+ 2!+ 3!+ 4!+ ...10!的和
//4! = 1*2*3*4
//5! = 1*2*3*4*5
//n! = 1*2*.....*n
////方法一
//int main()
//{
//	int n = 0;
//	//scanf("%d", &n);
//	int i = 0;
//	int ret = 1;
//	int sum = 0;
//	for (n = 1; n <= 10; n++)
//	{
//		ret = 1;
//		for (i = 1; i <= n; i++)
//		{
//			ret = ret * i;
//		}
//		sum = sum + ret;
//	}
//	
//	printf("%d\n", sum);
//
//
//	return 0;
//}



////方法二
//int main()
//{
//	int n = 0;
//	int ret = 1;
//	int sum = 0;
//	for (n = 1; n <= 10; n++)
//	{
//		ret = ret * n;
//		sum = sum + ret;
//	}
//	printf("%d\n", sum);
//
//	return 0;
//}


//死循环输出hehe
//i和arr中间 空多大空间，完全是取决于编译器实现，
//vc6.0 中 就这个代码arr和i之间没有空隙，gcc中就这个代码arr和i之间空一个int，vs中间空的是2个整型
//int main()
//{
//	int i = 0;
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	for (i = 0; i <= 12; i++)
//	{
//		arr[i] = 0;
//		printf("hehe\n");
//		//printf("%d ", arr[i]);
//	}
//
//	return 0;
//}



//栈区：局部变量、形式参数
//栈区上的内存的使用习惯是：先使用高地址的空间，在使用低地址的空间
//堆区：动态内存分配、malloc、realloc、calloc、free
//静态区：全局变量、静态变量 - static


//数组随着下标的增长，地址是由低到高变化的



//int main()
//{
//	int i = 0;
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//
//	printf("%p\n", &arr[12]);
//	printf("%p\n", &i);
//
//	for (i = 0; i <= 12; i++)
//	{
//		arr[i] = 0;
//		printf("hehe\n");
//	}
//	
//	return 0;
//
//}



//在数组传参，调试进⼊函数，如何在监视窗⼝观察数组的内容： 数组名, n 的形式

void test1(int arr3[])
{

}

void test2(int arr4[3][5])
{

}

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };
	test1(arr1);
	test2(arr2);

	return 0;
}




//程序员的三种境界
//1.看程序就是程序
//2.看程序就是内存
//3.看程序还是程序


//常见错误的归类
//1.编译型错误：一般都是语法错误，是最简单的，熟悉语法后会越来越少
//2.链接型错误：标识符名不存在、拼写错误、头文件没包含、引⽤的库不存在
//3.运行时错误：运行时错误，是千变万化的，需要借助调试，逐步定位问题，调试解决的是运行时问题